#include<iostream>
#include<cassert>
#include<unistd.h>
#include<string>

using namespace std;


void* thread1(void* args)
{
    cout<<"thread 1 returning"<<endl;
    int* p=(int*)malloc(sizeof(int));
    *p=1;
    //这里的return是返回给主线程的
    return (void*)p;
}
void* thread2(void* args)
{
    cout<<"thread 2 exiting"<<endl;
    int* p=(int*)malloc(sizeof(int));
    *p=2;
    pthread_exit((void*)p);
}
void* thread3(void* args)
{
    while(true)
    {
        sleep(1);
        cout<<"thread 3 running"<<endl;
    }
    return nullptr;
}
int main()
{
    pthread_t t1,t2,t3;
    void* ret;

    pthread_create(&t1,nullptr,thread1,nullptr);
    pthread_join(t1,&ret);
    printf("thread returnl:thread id:%X,thread code:%d\n",t1,*(int*)ret);

    pthread_create(&t2,nullptr,thread2,nullptr);
    pthread_join(t2,&ret);
    printf("thread return:thread id:%x,thread code:%d\n",t2,*(int*)ret);

    pthread_create(&t3,nullptr,thread3,nullptr);
    pthread_join(t3,nullptr);
    
    pthread_cancel(t3);
    if(ret == PTHREAD_CANCELED)
    {
        printf("thread return:thread id:%X,thread code:PTHREAD_CANCELED\n");
    }
    else
    {
        printf("thread return:thread id:%X,thread code:NULL\n");
    }
    return 0;
}
// void* thread1(void* args)
// {
//     cout<<"thread 1 running"<<endl;
//     int* p=(int*)malloc(sizeof(int));
//     *p=1;
//     return (void*)p;
// }
// void* thread(void* args)
// {
//     cout<<"thread 2 exiting"<<endl;
//     int* p=(int*)malloc(sizeof(int));
//     *p=2;
//     pthread_exit((void*)p);
// }
// void* thread3(void* args)
// {
//     while(true)
//     {
//         cout<<"thread 3 running"<<endl;
//         sleep(1);
//     }
//     return nullptr;
// }
// int main()
// {
    //因为这里值创建了一个线程所以这里才需要频繁地释放资源
//     pthread_t t1,t2,t3;
//     void* ret;
//     pthread_create(&t1,nullptr,thread1,nullptr);
//     pthread_join(t1,&ret);
//     printf("thread return:thread id:%X,thread code:%d\n",pthread_self(),*(int*)ret);
//     free(ret);

//     pthread_create(&t2,nullptr,thread2,nullptr);
//     pthread_join(t2,&ret);
//     printf("thread return:thread id:%X,thread code:%d\n",pthread_self(),*(int*)ret);    
//     return 0;
// }
// #define THREAD_NUM 5
// int tickets=10;
// //模拟抢票
// class ThreadData
// {
// public:
//     ThreadData(const string& name,pthread_mutex_t* mutex)
//     :_name(name)
//     ,_mutex(mutex)
//     {

//     }
// public:
//     string _name;
//     pthread_mutex_t* _mutex;    
// };
// void* getTickets(void* args)
// {
//     ThreadData* td=(ThreadData*)args;
//     while(true)
//     {
//         pthread_mutex_lock(td->_mutex);
//         if(tickets > 0)
//         {
//             sleep(1);
//             cout<<td->_name<<" send "<<tickets<<" tickets "<<endl;
//             tickets--;
//             pthread_mutex_unlock(td->_mutex);
//         }
//         else
//         {
//             sleep(1);
//             pthread_mutex_unlock(td->_mutex);
//             break;
//         }
//         sleep(1);
//     }
//     delete td;
//     return nullptr;
// }
// int main()
// {
//     pthread_mutex_t mutex;
//     pthread_mutex_init(&mutex,nullptr);
//     pthread_t tid[THREAD_NUM];
//     for(int i=0;i<THREAD_NUM;i++)
//     {
//         string name="thread";
//         name+=to_string(i+1);
//         ThreadData* td=new ThreadData(name,&mutex);
//         pthread_create(tid+i,nullptr,getTickets,(void*)td);
//     }
//     for(int i=0;i<THREAD_NUM;i++)
//     {
//         pthread_join(tid[i],nullptr);
//     }
//     pthread_mutex_destroy(&mutex);
//     return 0;
// }
// int tickets=20;
// class ThreadData
// {
// public:
//     ThreadData(const string& name,pthread_mutex_t* mutex)
//     :_mutex(mutex)
//     ,_name(name)
//     {

//     }
// public:
//     string _name;
//     pthread_mutex_t* _mutex;
// };
// void* getTickets(void* args)
// {
//     ThreadData* td=(ThreadData*)args;
//     while(true)
//     {
//         pthread_mutex_lock(td->_mutex);
//         if(tickets > 0)
//         {
//             sleep(1);
//             cout<<td->_name<<" send "<<tickets<<" tickets "<<endl;
//             tickets--;
//             pthread_mutex_unlock(td->_mutex);
//             pthread_mutex_unlock(td->_mutex);
//         }
//         else
//         {
//             pthread_mutex_unlock(td->_mutex);
//             break;
//         }
//         sleep(1);
//     }
//     delete td;
//     return nullptr;
// }
// int main()
// {
//     pthread_mutex_t mutex;
//     pthread_mutex_init(&mutex,nullptr);
//     pthread_t tid[THREAD_NUM];
//     for(int i=0;i<THREAD_NUM;i++)
//     {
//         string name="thread";
//         name+=to_string(i+1);
//         ThreadData* td=new ThreadData(name,&mutex);
//         //看来这里不单单只能传入字符串说明还可以传一个对象过去
//         pthread_create(tid+i,nullptr,getTickets,(void*)td);
//     }
//     for(int i=0;i<THREAD_NUM;i++)
//     {
//         pthread_join(tid[i],nullptr);
//     }
//     pthread_mutex_destroy(&mutex);
//     return 0;
// }
// int tickets=20;
// class ThreadData
// {
//     public:
//     ThreadData(const string& name,pthread_mutex_t* mutex)
//     :_name(name)
//     ,_mutex(mutex)
//     {

//     }
//     public:
//     string _name;
//     pthread_mutex_t* _mutex;
// };
// void* getTickets(void* args)
// {
//     ThreadData* td=(ThreadData*)args;
//     while(true)
//     {
//         int n=pthread_mutex_lock(td->_mutex);
//         assert(n==0);
//         if(tickets > 0)
//         {
//             sleep(1);
//             cout<<td->_name<<" send "<<tickets<<" tickets "<<endl;
//             tickets--;
//             n=pthread_mutex_unlock(td->_mutex);
//             assert(n == 0);
//         }
//         else
//         {
//             pthread_mutex_unlock(td->_mutex);
//             assert(n == 0);
//             break;
//         }
//         sleep(1);
//     }
//     delete td;
//     return nullptr;
// }
// int main()
// {
//     pthread_mutex_t mutex;
//     pthread_mutex_init(&mutex,nullptr);
//     pthread_t tid[THREAD_NUM];
//     for(int i=0;i<THREAD_NUM;i++)
//     {
//         string name="thread";
//         name+=to_string(i+1);
//         ThreadData* td=new ThreadData(name,&mutex);
//         pthread_create(tid+i,nullptr,getTickets,(void*)td);
//     }
//     for(int i=0;i<THREAD_NUM;i++)
//     {
//         pthread_join(tid[i],nullptr);
//     }
//     pthread_mutex_destroy(&mutex);
//     return 0;
// }
// class ThreadData
// {
// public:
//     ThreadData(const std::string &n,pthread_mutex_t *pm):tname(n), pmtx(pm)
//     {}
// public:
//     std::string tname;
//     pthread_mutex_t *pmtx;
// };

// void *getTickets(void *args)
// {
//     // int myerrno = errno;
//     ThreadData *td = (ThreadData*)args;
//     while(true)
//     {
//         // 抢票逻辑
//         int n = pthread_mutex_lock(td->pmtx);
//         assert(n == 0);
//         // 临界区
//         if(tickets > 0) // 1. 判断的本质也是计算的一种
//         {
//             usleep(rand()%1500);
//             printf("%s: %d\n", td->tname.c_str(), tickets);
//             tickets--; // 2. 也可能出现问题
//             n = pthread_mutex_unlock(td->pmtx);
//             assert(n == 0);
//         }
//         else{
//             n = pthread_mutex_unlock(td->pmtx);
//             assert(n == 0);
//             break;
//         }
        
//         // 抢完票，其实还需要后续的动作
//         usleep(rand()%2000);
//         //  errno = myerrno;
//     }
//     delete td;
//     return nullptr;
// }

// int main()
// {
//     //time_t start = time(nullptr);
//     pthread_mutex_t mtx;
//     pthread_mutex_init(&mtx, nullptr);

//     //srand((unsigned long)time(nullptr) ^ getpid() ^ 0x147);
//     pthread_t t[THREAD_NUM];
//     // 多线程抢票的逻辑
//     for(int i = 0; i < THREAD_NUM; i++)
//     {
//         std::string name = "thread ";
//         name += std::to_string(i+1);
//         ThreadData *td = new ThreadData(name, &mtx);
//         pthread_create(t + i, nullptr, getTickets, (void*)td);
//     }

//     for(int i = 0; i < THREAD_NUM; i++)
//     {
//         pthread_join(t[i], nullptr);
//     }

//     pthread_mutex_destroy(&mtx);

//     time_t end = time(nullptr);

//     //cout << "cast: " << (int)(end - start) << "S" << endl;
// }
// class ThreadData
// {
//     ThreadData(const string& name,pthread_mutex_t* mutex)
//     :_name(name)
//     ,_mutex(mutex)
//     {

//     }
// public:
//     string _name;
//     pthread_mutex_t* _mutex;
// };
// void* getTickets(void* args)
// {
//     ThreadData* td=(ThreadData*)args;
//     while(true)
//     {
//         int n=pthread_mutex_lock(td->_mutex);
//         assert(n == 0);
//         if(tickets > 0)
//         {
//             sleep(1);
//             cout<<td->_name<<" send "<<tickets<<"tickets"
//             <<endl;
//             tickets--;
//             int n=pthread_mutex_unlock(td->_mutex);
//             assert(n == 0);
//         }
//         else
//         {
//             pthread_mutex_unlock(td->_mutex);
//             assert(n == 0);
//             break;
//         }
//         sleep(1);
//     }
//     //执行完任务之后就将空间释放掉
//     delete td;
//     return nullptr;
// }
// int main()
// {
//     pthread_mutex_t mutex;
//     pthread_mutex_init(&mutex,nullptr);
    
//     pthread_t tid[THREAD_NUM];
//     for(int i=0;i<THREAD_NUM;i++)
//     {
//         string name="thread";
//         name+=to_string(i+1);
//         ThreadData* td=new ThreadData(name,&mutex);
//         pthread_create(tid+i,nullptr,getTickets,(void*)td);
//     }
//     for(int i=0;i<THREAD_NUM;i++)
//     {
//         pthread_join(tid[i],nullptr);
//     }
//     pthread_mutex_destroy(&mutex);
//     return 0;
// }
// #define THREAD_NUM 5
// int tickets = 5;
// class ThreadData
// {
//     ThreadData(const string& name,pthread_mutex_t mutex)
//     :_name(name)
//     ,_mutext(mutex)
//     {

//     }
// public:
//     string _name;
//     pthread_mutex_t _mutex;
// };
// void* getTickets(void* args)
// {
//     ThreadData* td=(ThreadData*)args;
//     while(true)
//     {
//         pthread_mutex_lock(&td->_mutex);
//         if(tickets > 0)
//         {
//             sleep(1);
//             cout<<td->_name<<" send "<<tickets<<" tickets "<<endl;
//             tickets--;
//             pthread_mutex_unlock(&td->_mutex);
//         }
//         else
//         {
//             pthread_mutex_unlock(&td->_mutex);
//             break;
//         }
//         sllep(1);
//     }
//     return nullptr;
// }
// int main()
// {
//     srand((unsigned long)time(nullptr)^pthread_self());
//     time_t start=time(nullptr);
//     pthread_mutex_t mutex;
//     pthread_mutex_init(&mutex);
//     pthread_t tid[THREAD_NUM];
//     for(int i=0;i<THREAD_NUM;i++)
//     {
//         string name="thread";
//         name+=to_string(i+1);
//         ThreadData* td=new ThreadData(name,mutex);
//         pthread_create(tid+i,nullptr,getTickets,(void*)td);
//     }
//     for(int i=0;i<THREAD_NUM;i++)
//     {
//         pthread_join(tid+i,nullptr);
//     }
//     pthread_mutex_destroy(&mutex);
    
//     time_t end=time(nullptr);
//     cout<<"cast:"<<end-start<<"s"<<endl;
//     return 0;
// }
// #define THREAD_NUM 5
// int tickets=100;

// class ThreadData
// {
// public:
//     ThreadData(const string& name,pthread_mutex_t mutex)
//     :_name(name)
//     ,_mutex(mutex)
//     {

//     }
// public:
//     string _name;
//     pthread_mutex_t _mutex;
// };

// void* getTickets(void* args)
// {
//     ThreadData* td=(ThreadData*)args;
//     while(true)
//     {
//         pthread_mutex_lock(&td->_mutex);
//         if(tickets > 0)
//         {
//             sleep(1);
//             cout<<td->_name<<" send "<<tickets<<" tickets "<<endl;
//             tickets--;
//             pthread_mutex_unlock(&td->_mutex);
//         }
//         else
//         {
//             pthread_mutex_unlock(&td->_mutex);
//             break;
//         }
//     sleep(1);
//     }
//     return nullptr;
// }
// int main()
// {
//     pthread_mutex_t mutex;
//     pthread_mutex_init(&mutex,nullptr);
//     pthread_t tid[THREAD_NUM];
//     for(int i=0;i<THREAD_NUM;i++)
//     {
//         string name="thread";
//         name+=to_string(i+1);
//         //到这里的时候顺便分配一下信息
//         ThreadData* td=new ThreadData(name,mutex);
//         pthread_create(tid+i,nullptr,getTickets,(void*)td);
//     }

//     for(int i=0;i<THREAD_NUM;i++)
//     {
//         pthread_join(tid+i,nullptr);
//     }
//     pthread_mutex_destroy(&mutex);
//     return 0;
// }
// #define THREAD_NUM 5
// int tickets=100;
// class ThreadData
// {
// public:
//     ThreadData(const string& name,pthread_mutex_t* mutex)
//     :_name(name)
//     ,_mutex(mutex)
//     {

//     }
// public:
//     string _name;
//     pthread_mutex_t* _mutex;
// };
// //这里搞清楚你要传递的是一个对象
// void* getTickets(void* args)
// {
    
//     ThreadData* td=(ThreadData*)args;
//     while(true)
//     {
//         int n=pthread_mutex_lock(td->_mutex);
//         assert(n==0);
//         if(tickets > 0)
//         {
//             sleep(1);
//             cout<<td->_name<<" send "<<tickets
//             <<" tickets "<<endl;
//             tickets--;
//             int n=pthread_mutex_unlock(td->_mutex);
//         }
//         else
//         {
//             int n=pthread_mutex_unlock(td->_mutex);
//             assert(n==0);
//             break;
//         }
//         sleep(1);
//     }
//     delete td;
//     return nullptr;
// }
// int main()
// {
//     time_t start=time(nullptr);
//     pthread_mutex_t mutex;
//     pthread_mutex_init(&mutex,nullptr);
//     srand((unsigned long)time(nullptr)^pthread_self());
//     pthread_t tid[THREAD_NUM];
//     for(int i=0;i<THREAD_NUM;i++)
//     {
//         string name="thread"; 
//         name+=to_string(i+1);
//         //创建出来本身就是一个数组
//         ThreadData* td=new ThreadData(name,&mutex);
//         pthread_create(tid+i,nullptr,getTickets,(void*)td);
//     }

//     for(int i=0;i<THREAD_NUM;i++)
//     {
//         pthread_join(tid[i],nullptr);
//     }
//     pthread_mutex_destroy(&mutex);
//     time_t end=time(nullptr);
//     cout<<"cast:"<<end-start<<"s"<<endl;
//     return 0;
// }
// #define THREAD_NUM 5
// int tickets=100;
// class ThreadData
// {
// public:
//     ThreadData(const string& name,pthread_mutex_t* mutex)
//     :_name(name)
//     ,_mutex(mutex)
//     {

//     }
// public:
//     string _name;
//     pthread_mutex_t* _mutex;
// };

// void* getTickets(void* args)
// {
//     ThreadData* td=(ThreadData*)args;
//     while(true)
//     {
//         int n=pthread_mutex_lock(td->_mutex);
//         assert(n==0);
//         if(tickets > 0)
//         {
//             sleep(1);
//             cout<<td->_name.c_str()<<" send "<<tickets
//             <<" tickets "<<endl;
//             tickets--;
//             n=pthread_mutex_unlock(td->_mutex);
//             assert(n==0);
//         }
//         else
//         {
//             //如果你要退出的话，把锁留下再退出
//             n=pthread_mutex_lock(td->_mutex);
//             assert(n==0);
//             break;
//         }
//         sleep(1);
//     }
//     delete td;
//     return nullptr;
// }

// int main()
// {
//     //设置起始时间
//     time_t start=time(nullptr);
//     pthread_mutex_t mutex;
//     pthread_mutex_init(&mutex,nullptr);

//     srand((unsigned long)time(nullptr)^getpid());
//     pthread_t tid[THREAD_NUM];
//     for(int i=0;i<THREAD_NUM;i++)
//     {
//         string name="thread";
//         name+=to_string(i+1);
//         ThreadData* td=new ThreadData(name,&mutex);
//         pthread_create(tid+i,nullptr,getTickets,(void*)td);
//     }

//     for(int i=0;i<THREAD_NUM;i++)
//     {
//         pthread_join(tid[i],nullptr);
//     }
//     pthread_mutex_destroy(&mutex);
    
//     time_t end=time(nullptr);
//     cout<<"cast"<<(int)(end-start)<<"s"<<endl; 
//     return 0;
// }